package com.hyk.commonLib.common.utils;

import android.annotation.SuppressLint;
import android.graphics.drawable.Drawable;
import android.util.Size;
import android.widget.ImageView;

import androidx.annotation.DrawableRes;
import androidx.annotation.IntDef;
import androidx.annotation.Nullable;

import com.bumptech.glide.Glide;
import com.bumptech.glide.RequestBuilder;
import com.bumptech.glide.load.DataSource;
import com.bumptech.glide.load.engine.GlideException;
import com.bumptech.glide.load.resource.bitmap.CircleCrop;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.target.Target;
import com.hyk.commonLib.common.entity.ImageSource;
import com.hyk.commonLib.common.exception.CustomException;

import java.io.File;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

import jp.wasabeef.glide.transformations.BlurTransformation;
import lombok.SneakyThrows;

/**
 * 拆分图片加载与图片下载，将图片下载封装为文件下载
 */
public class ImageLoader {

    // region   =================================================  string path  ======================================================
    public static void load(String url, ImageView img) {
        load(url, img, null, null);
    }

    public static void load(String url, ImageView img, Option option) {
        load(url, img, null, option);
    }

    public static void load(String url, ImageView img, OnResLoadListener listener) {
        load(url, img, listener, null);
    }

    @SuppressLint("CheckResult")
    public static void load(String url, ImageView img, OnResLoadListener listener, Option option) {
        RequestOptions options = new RequestOptions();
        // .override(Target.SIZE_ORIGINAL);
        RequestBuilder<Drawable> requestBuilder = Glide.with(AppUtils.getAppContext())
                .load(url)
                .thumbnail(0.1F);
        if (listener != null) {
            requestBuilder.listener(new RequestListener<Drawable>() {
                @Override
                public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
                    listener.onFailed(e);
                    return false;
                }

                @Override
                public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
                    listener.onSuccess(ImageSource.fromUrl(url));
                    return false;
                }
            });
        }
        if (option != null) {
            option.applyConfig(options, requestBuilder);
        }
        requestBuilder.apply(options).into(img);
    }

    // endregion


    // region   =================================================  drawable res  ======================================================

    public static void load(@DrawableRes int drawableRes, ImageView img) {
        load(drawableRes, img, null, null);
    }

    public static void load(@DrawableRes int drawableRes, ImageView img, Option option) {
        load(drawableRes, img, null, option);
    }

    public static void load(int drawableRes, ImageView img, OnResLoadListener listener) {
        load(drawableRes, img, listener, null);
    }

    @SuppressLint("CheckResult")
    public static void load(int drawableRes, ImageView img, OnResLoadListener listener, Option option) {
        RequestOptions options = new RequestOptions();
        RequestBuilder<Drawable> requestBuilder = Glide.with(AppUtils.getAppContext())
                .load(drawableRes)
                .thumbnail(0.1F)
                .apply(options);
        if (listener != null) {
            requestBuilder.listener(new RequestListener<Drawable>() {
                @Override
                public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
                    listener.onFailed(e);
                    return false;
                }

                @Override
                public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
                    listener.onSuccess(ImageSource.fromDrawableRes(drawableRes));
                    return false;
                }
            });
        }
        if (option != null) {
            option.applyConfig(options, requestBuilder);
        }
        requestBuilder.apply(options).into(img);
    }

    // endregion


    // region   =================================================  File imageFile  ======================================================

    public static void load(File imageFile, ImageView img) {
        load(imageFile, img, null, null);
    }

    public static void load(File imageFile, ImageView img, Option option) {
        load(imageFile, img, null, option);
    }

    public static void load(File imageFile, ImageView img, OnResLoadListener listener) {
        load(imageFile, img, listener, null);
    }

    @SuppressLint("CheckResult")
    public static void load(File imageFile, ImageView img, OnResLoadListener listener, Option option) {
        RequestOptions options = new RequestOptions();
        // .override(Target.SIZE_ORIGINAL)
        RequestBuilder<Drawable> requestBuilder = Glide.with(AppUtils.getAppContext())
                .load(imageFile)
                .thumbnail(0.1F)
                .apply(options);
        if (listener != null) {
            requestBuilder.listener(new RequestListener<Drawable>() {
                @Override
                public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
                    listener.onFailed(e);
                    return false;
                }

                @Override
                public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
                    listener.onSuccess(ImageSource.fromFile(imageFile));
                    return false;
                }
            });
        }
        if (option != null) {
            option.applyConfig(options, requestBuilder);
        }
        requestBuilder.apply(options).into(img);
    }

    // endregion


    // region   =================================================  File imageFile  ======================================================

    public static void load(ImageSource imageSource, ImageView img) {
        load(imageSource, img, null, null);
    }

    public static void load(ImageSource imageSource, ImageView img, Option option) {
        load(imageSource, img, null, option);
    }

    public static void load(ImageSource imageSource, ImageView img, OnResLoadListener listener) {
        load(imageSource, img, listener, null);
    }

    @SuppressLint("CheckResult")
    @SneakyThrows
    public static void load(ImageSource imageSource, ImageView img, OnResLoadListener listener, Option option) {
        RequestOptions options = new RequestOptions();
        // .override(Target.SIZE_ORIGINAL)
        RequestBuilder<Drawable> requestBuilder;
        if (imageSource.hasUrl()) {
            requestBuilder = Glide.with(AppUtils.getAppContext()).load(imageSource.getImgUrl());
        } else if (imageSource.hasFile()) {
            requestBuilder = Glide.with(AppUtils.getAppContext()).load(imageSource.getImgFile());
        } else if (imageSource.hasDrawable()) {
            requestBuilder = Glide.with(AppUtils.getAppContext()).load(imageSource.getImgDrawable());
        } else if (imageSource.hasDrawableRes()) {
            requestBuilder = Glide.with(AppUtils.getAppContext()).load(imageSource.getImgDrawableRes());
        } else if (imageSource.hasLottieRes()) {
//            if (img instanceof LottieAnimationView) {
//                imageSource.getLottieRes().loadAnim((LottieAnimationView) img);
//                listener.onSuccess(imageSource);
//            }
//            return;
            requestBuilder = Glide.with(AppUtils.getAppContext()).load(imageSource.convertToDrawable());
        } else {
            throw new CustomException("暂不支持此类型图片");
        }
        requestBuilder
                .thumbnail(0.1F)
                .apply(options);
        if (listener != null) {
            requestBuilder.listener(new RequestListener<Drawable>() {
                @Override
                public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
                    listener.onFailed(e);
                    return false;
                }

                @Override
                public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
                    listener.onSuccess(imageSource);
                    return false;
                }
            });
        }
        if (option != null) {
            option.applyConfig(options, requestBuilder);
        }
        requestBuilder.apply(options).into(img);
    }

    // endregion

    public static void clearCache() {
        Glide.get(AppUtils.getAppContext()).clearMemory();
        new Thread(() -> {
            Glide.get(AppUtils.getAppContext()).clearDiskCache();
        }).start();
    }

    public static class Option {
        @Retention(RetentionPolicy.SOURCE)
        @IntDef({OverrideType.DEFAULT,
                OverrideType.ORIGINAL,
                OverrideType.CUSTOM,})
        private @interface OverrideType {
            int DEFAULT = 0;
            int ORIGINAL = 1;
            int CUSTOM = 2;
        }

        private ImageSource placeholder;
        private boolean circle;
        private int blurRadius;
        @OverrideType
        private int overrideType = OverrideType.DEFAULT;
        /**
         * 自定义长宽，{@link #overrideType} 为 {@link OverrideType#CUSTOM} 时使用
         */
        private Size overrideSize;

        public static Option get() {
            return new Option();
        }

        public Option circle() {
            this.circle = true;
            return this;
        }

        public Option setPlaceholder(ImageSource placeholder) {
            this.placeholder = placeholder;
            return this;
        }

        public Option blur(int blurRadius) {
            this.blurRadius = blurRadius;
            return this;
        }

        public Option originalSize() {
            overrideType = OverrideType.ORIGINAL;
            return this;
        }

        public Option customSize(int overrideWidth, int overrideHeight) {
            overrideType = OverrideType.CUSTOM;
            this.overrideSize = new Size(overrideWidth, overrideHeight);
            return this;
        }

        public Option customSize(int overrideSize) {
            return customSize(overrideSize, overrideSize);
        }

        @SuppressLint("CheckResult")
        private void applyConfig(RequestOptions options, RequestBuilder<Drawable> requestBuilder) {
            if (circle) {
                requestBuilder.apply(RequestOptions.bitmapTransform(new CircleCrop()));
            }
            if (blurRadius > 0) {
                requestBuilder.apply(RequestOptions.bitmapTransform(new BlurTransformation(blurRadius)));
            }
            if (placeholder != null) {
                if (placeholder.hasDrawable()) {
                    options.placeholder(placeholder.getImgDrawable());
                } else if (placeholder.hasDrawableRes()) {
                    options.placeholder(placeholder.getImgDrawableRes());
                } else if (placeholder.canConvertToDrawable()) {
                    options.placeholder(placeholder.convertToDrawable());
                }
            }
            switch (overrideType) {
                case OverrideType.CUSTOM:
                    options.override(overrideSize.getWidth(), overrideSize.getHeight());
                    break;
                case OverrideType.DEFAULT:
                    break;
                case OverrideType.ORIGINAL:
                    options.override(Target.SIZE_ORIGINAL);
                    break;
            }
        }
    }

    public interface OnResLoadListener {
        void onFailed(Exception e);

        void onSuccess(ImageSource imageSource);
    }

}
